package com.senter.data.dbflow;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.helper.widget.Flow;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.raizlabs.android.dbflow.config.FlowManager;
import com.raizlabs.android.dbflow.sql.language.CompletedTrigger;
import com.raizlabs.android.dbflow.sql.language.Method;
import com.raizlabs.android.dbflow.sql.language.OperatorGroup;
import com.raizlabs.android.dbflow.sql.language.OrderBy;
import com.raizlabs.android.dbflow.sql.language.SQLite;
import com.raizlabs.android.dbflow.sql.language.Trigger;
import com.raizlabs.android.dbflow.structure.database.DatabaseWrapper;
import com.raizlabs.android.dbflow.structure.database.transaction.DefaultTransactionManager;
import com.raizlabs.android.dbflow.structure.database.transaction.FastStoreModelTransaction;
import com.raizlabs.android.dbflow.structure.database.transaction.ITransaction;
import com.raizlabs.android.dbflow.structure.database.transaction.Transaction;
import com.senter.data.dbflow.databinding.ActivityMainBinding;
import com.senter.data.dbflow.db.DemoDataBase;
import com.senter.data.dbflow.db.dao.PersonDao;
import com.senter.data.dbflow.model.Person;
import com.senter.data.dbflow.model.PersonLog;
import com.senter.data.dbflow.model.PersonLog_Table;
import com.senter.data.dbflow.model.Person_Table;
import com.senter.data.dbflow.utils.ChineseName;
import com.senter.data.dbflow.utils.DataUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.PriorityBlockingQueue;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";

    private Context mContext;

    private ActivityMainBinding binding;

    private RecyclerView personListView;
    private List<Person> personList;
    private GridLayoutManager personGridLayoutManager;
    private PersonAdapter adapter;

    private PersonDao personDao;
    private ChineseName chineseName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        initView();
        initData();
    }

    private void initData() {
        personDao = new PersonDao();
        chineseName = new ChineseName();

        OrderBy orderBy = OrderBy.fromProperty(Person_Table.id).ascending();
        personList = personDao.selectList(0, 100, orderBy);

        adapter = new PersonAdapter(mContext);
        personListView.setAdapter(adapter);
        adapter.setData(personList);
    }

    private void initView() {
        binding.titleLayout.title.setText("DBFlow演示");
        personListView = binding.recyclerView;
        personGridLayoutManager = new GridLayoutManager(MainActivity.this, 1);
        personListView.setLayoutManager(personGridLayoutManager);
        binding.addButton.setOnClickListener(this);
        binding.deleteButton.setOnClickListener(this);
        binding.updateButton.setOnClickListener(this);
        binding.cleanButton.setOnClickListener(this);
        binding.triggerButton.setOnClickListener(this);
    }

    private void refreshData() {
        OrderBy orderBy = OrderBy.fromProperty(Person_Table.id).ascending();
        personList = personDao.selectList(0, 100, orderBy);
        adapter.setData(personList);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.add_button:
                addData();
                break;
            case R.id.delete_button:
                deleteData();
                break;
            case R.id.update_button:
                updateData();
                break;
            case R.id.clean_button:
                cleanData();
                break;
            case R.id.trigger_button:
                transactionTest();
                break;
            default:
                break;
        }
    }

    private void addData() {
//        Person person = new Person();
//        person.setName(chineseName.getName());
//        int sex = (int) (10 * Math.random()) % 2;
//        person.setSex(sex == 0 ? "男" : "女");
//        person.setAge(DataUtil.getAge());
//        person.setEmail(chineseName.getName() + "@senter.com.cn");
//        person.save();

        Person person = new Person();
//        person.setId(19);
        person.setName("张三");
        person.setAge(50);
        person.setSex("男");
        person.setEmail("zhangsan@senter.com.cn");
        person.setAddress("111");
        person.setRemark("备注信息");
        boolean isSave = person.save();         // save 方法是会先查询数据库里面是否存在同插入数据主键相对应的数据，如果存在，则保存更新数据。不存在的话，再插入数据
//        long id = person.insert();              // insert 不会查询,而是直接插入,如果有相同主键的数据则直接抛出异常


//        Person person1 = new Person();
//        person.setId(1);
//        person.delete();
//        boolean isDelete = FlowManager.getModelAdapter(Person.class).delete(person1);

        refreshData();
    }

    private void deleteData() {
        Person personList = SQLite.select(Method.max(Person_Table.age)).from(Person.class).querySingle(); // 查询年龄最大的
        Log.d(TAG, "deleteData: " + personList.getAge());
    }

    private void updateData() {
        Person person = new Person();
        person.setId(1);
        person.setName("李四");           // 原名是张三,要修改成李
        person.update();
        boolean isUpdate = FlowManager.getModelAdapter(Person.class).update(person);
        refreshData();
    }

    private List<Person> selectList() {
        List<Person> personList = null;
        personList = SQLite.select().from(Person.class).queryList();            // 查询所有,没有条件
        // 添加查询条件
        OperatorGroup operators = OperatorGroup.clause();
        operators.and(Person_Table.id.eq(1));               // and person.id = 1
        operators.and(Person_Table.name.eq("张三"));         // and person.name = '张三'
        operators.or(Person_Table.email.like("%senter%"));  // or person.email like '%senter%'
        personList = SQLite.select().from(Person.class).where(operators).queryList();

        // 查询单个数据
        Person p1 = SQLite.select().from(Person.class).querySingle();
        OperatorGroup operators1 = OperatorGroup.clause();
        operators1.and(Person_Table.name.eq("张三"));
        Person p2 = SQLite.select().from(Person.class).where(operators1).querySingle();

        // OrderBy Limit + offset 分页
        SQLite.select().from(Person.class).where(operators).orderBy(Person_Table.id, true).queryList();  // true为'ASC'升序, false为'DESC'降序
        SQLite.select().from(Person.class).where(operators).orderBy(Person_Table.id, true).limit(0).offset(10).queryList();     // 从第0个开始查询10条数据
        SQLite.select().from(Person.class).groupBy(Person_Table.name).queryList();                              // 张三同名的人员

        return personList;
    }

    // 事物+异步操作
    private void transactionTest() {

        // 同步的事物处理的操作
//        FlowManager.getDatabase(DemoDataBase.class).executeTransaction(new ITransaction() {
//            @Override
//            public void execute(DatabaseWrapper databaseWrapper) {
//                for (int i = 0; i < 100; i++) {
//                    Person person = new Person();
//                    person.setName("P"+i);
//                    person.setSex(i%2 == 0 ? "男" : "女");
//                    person.save(databaseWrapper);
//                }
//            }
//        });

        // 异步事物操作
        FlowManager.getDatabase(DemoDataBase.class).beginTransactionAsync(new ITransaction() {
            @Override
            public void execute(DatabaseWrapper databaseWrapper) {
                // save
                for (int i = 0; i < 5; i++) {
                    Person p = new Person();
                    p.setName("tt" + i);
                    p.setSex("男");
                    p.save(databaseWrapper);
                }
                // update
                Person person = new Person();
                person.setId(11);
                person.setName("11000");
                person.insert(databaseWrapper);
                // save
            }
        }).success(new Transaction.Success() {
            @Override
            public void onSuccess(@android.support.annotation.NonNull @NonNull Transaction transaction) {
                Log.d(TAG, "onSuccess: 执行成功");
            }
        }).error(new Transaction.Error() {
            @Override
            public void onError(@android.support.annotation.NonNull @NonNull Transaction transaction, @android.support.annotation.NonNull @NonNull Throwable error) {
                Log.d(TAG, "onError: 执行失败");
            }
        }).build().execute();

        // 异步的事物处理,保存列表
        List<Person> personList1 = new ArrayList<Person>();
        FlowManager.getDatabase(DemoDataBase.class).beginTransactionAsync(FastStoreModelTransaction.insertBuilder(FlowManager.getModelAdapter(Person.class))
                .addAll(personList1)
                .build()).success(new Transaction.Success() {
            @Override
            public void onSuccess(@android.support.annotation.NonNull @NonNull Transaction transaction) {

            }
        }).error(new Transaction.Error() {
            @Override
            public void onError(@android.support.annotation.NonNull @NonNull Transaction transaction, @android.support.annotation.NonNull @NonNull Throwable error) {

            }
        }).build().execute();

    }

    private void cleanData() {
        SQLite.delete().from(Person.class).query();
        refreshData();
    }

    private void triggerTest(PersonLog personLog) {
        CompletedTrigger<Person> trigger = Trigger.create("PersonTrigger")
                .after().updateOn(Person.class, Person_Table.name)
                .begin(SQLite.insert(PersonLog.class).columnValues(PersonLog_Table.oldName.eq(""), PersonLog_Table.newName.eq("new.Name"), PersonLog_Table.date.eq(System.currentTimeMillis())));


        // starts a trigger
        trigger.enable();

        // stops a trigger
//        trigger.disable();
    }

    class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.ViewHolder> {
        private List<Person> mData = new ArrayList<Person>();
        private Context mContext;

        public PersonAdapter(Context context) {
            this.mContext = context;
        }

        public void add(int pos, Person item) {
            mData.add(pos, item);
            notifyItemInserted(pos);
        }

        public void prepend(@NonNull List<Person> items) {
            mData.addAll(0, items);
            notifyDataSetChanged();
        }

        public void append(@NonNull List<Person> items) {
            mData.addAll(items);
            notifyDataSetChanged();
        }

        public Person get(int pos) {
            return mData.get(pos);
        }

        public void setData(@Nullable List<Person> list) {
            mData.clear();
            if (list != null) {
                mData.addAll(list);
            }
            notifyDataSetChanged();
        }

        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View v = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_show, parent, false);
            return new ViewHolder(v);
        }

        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            Person p = mData.get(position);
            if (p != null) {
                holder.tv_id.setText(String.valueOf(p.getId()));
                holder.tv_name.setText(p.getName());
                holder.tv_age.setText(String.valueOf(p.getAge()));
                holder.tv_email.setText(p.getEmail());
            }
        }

        @Override
        public int getItemCount() {
            return mData.size();
        }

        class ViewHolder extends RecyclerView.ViewHolder {
            View myView;
            TextView tv_id;
            TextView tv_name;
            TextView tv_age;
            TextView tv_email;

            public ViewHolder(@NonNull View itemView) {
                super(itemView);
                myView = itemView;
                tv_id = itemView.findViewById(R.id.id_text);
                tv_name = itemView.findViewById(R.id.name_text);
                tv_age = itemView.findViewById(R.id.age_text);
                tv_email = itemView.findViewById(R.id.email_text);
            }
        }
    }
}